#pragma once

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string>
#include <functional>
#include "Socket.hpp"
#include "log.hpp"

using func_t = std::function<std::string(const std::string&)>;

class TcpServer
{
public:
    TcpServer(int port, func_t callback)
        :_port(port), _callback(callback)
    { }

    void init()
    {
        _serversock.Socket();
        _serversock.Bind(_port);
        _serversock.Listen();
    }

    void start()
    {
        while(true)
        {
            std::string clientip;
            uint16_t clientport;
            int fd = _serversock.Accept(&clientip, &clientport);
            if(fd < 0) { continue; }
            pid_t id = fork();
            if(id == 0)
            {
                //取消父进程的阻塞等待
                if(fork() > 0) { exit(0); }
                //计算服务
                while(true)
                {
                    std::string inbuffer;
                    char buff[1024];
                    while(true)
                    {
                        //读取数据
                        buff[0] = 0;
                        ssize_t n = read(fd, buff, sizeof(buff));
                        buff[n] = 0;
                        inbuffer += buff;
                        //当前报文合法，停止读取
                        if(Decode(inbuffer)) { break; }
                    }
                    //执行计算 此时package一定是一个完整的报文
                    std::string res_str = _callback(inbuffer);
                    //写回数据
                    std::cout << "result server:" << std::endl;
                    std::cout << res_str << std::endl;
                    ssize_t n = write(fd, res_str.c_str(), res_str.size());
                }
                exit(0);
            }
            close(fd);
            waitpid(id, nullptr, 0);
        }
    }

private:
    Sock _serversock;
    int _port;
    func_t _callback;
};